/**
 * @file dial_switch.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_DIAL_SWITCH != 0

#include <stdio.h>
#include "hal/dm/cJSON.h"
/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_obj_t * append_obj(lv_obj_t * page);
static lv_obj_t * dial_image_add(lv_obj_t * page);
static lv_res_t dial_switch_page_scrl_signal(lv_obj_t * page_scrl, lv_signal_t sign, void * param);
static int aligned_width(int val, lv_coord_t move_width);
static lv_dail_switch_obj_ext_t * dial_switch_get_ext(lv_obj_t * element);
static lv_res_t page_scrl_signal_handler(lv_obj_t * page_scrl, lv_signal_t sign, void * param);
static void dial_switch_prepare_destory(lv_obj_t * activity_obj);
static void dial_switch_add_element(lv_obj_t * element);
static lv_obj_t * dial_switch_get_page_scrl(lv_obj_t * element);
static void dial_list_init(dial_list_t * dial_list, uint8_t psm);
static void dial_list_destory(dial_list_t * dial_list);
static uint8_t dial_switch_get_config(char * conf_path, dial_conf_t * dial_conf);
static void dial_element_setting(lv_obj_t * obj, lv_event_t event);
static void dial_switch_get_dial_list(char * list_path, dial_list_t * dial_list);
static void dial_switch_psm_destroy(lv_anim_t * a);
/**********************
 *  STATIC VARIABLES
 **********************/
static lv_signal_cb_t ancient_page_scrl_signal;
static lv_signal_cb_t ancient_img_signal;
static dial_list_t diallist = {};

/**********************
 *      MACROS
 **********************/
#define DIAL_PSM_SET_TIP_TIME   1000
/**********************
 *   GLOBAL FUNCTIONS
***********************/
lv_obj_t * dial_switch_create(lv_obj_t * activity_obj, uint8_t psm)
{
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_DIAL_SWITCH;
        activity_ext.create = NULL;
        activity_ext.prepare_destory = dial_switch_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(activity_obj == NULL) return NULL;
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) return NULL;
    /*when pressing, y is not updated. When press lost  */
    lv_watch_obj_set_anim_mode(obj, LV_WATCH_LEFT_OR_RIGHT_SLIDE_CALLBACK);
    lv_watch_obj_ext_t * watch_obj_ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_watch_obj_ext_t));
    if(watch_obj_ext == NULL) return NULL;

    /*Allocate the object type specific extended data*/
    lv_dail_switch_obj_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_dail_switch_obj_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;
    /*do not memset ext, since it include lv_watch_obj_ext_t lv_watch_obj*/
    //memset(ext, 0, sizeof(lv_dail_switch_obj_ext_t));

    ext->psm = psm;
    ext->body_padding_inner = 30;
    ext->append_width = 50;
    ext->move_width = ext->body_padding_inner + ext->append_width + (lv_obj_get_width(obj) / 2 - ext->append_width); //130;
    ext->cur_img_id = 0;
    ext->dail_cur_type = 0;
    ext->imgs = NULL;
    ext->del_activity_en = true;
    ext->img_cnt = 0;
    dial_list_init(&diallist, psm);

    lv_obj_t * page = lv_page_create(obj, NULL);
    LV_ASSERT_MEM(page);
    if(page == NULL) return NULL;
    lv_obj_set_size(page, lv_obj_get_width(obj), lv_obj_get_height(obj));
    lv_page_set_scrollbar_mode(page, LV_SCROLLBAR_MODE_OFF);
    lv_obj_set_style_local_bg_opa(page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
    lv_obj_set_style_local_bg_opa(page, LV_PAGE_PART_SCROLLABLE, LV_STATE_DEFAULT, LV_OPA_0);
    lv_obj_set_style_local_pad_inner(page, LV_PAGE_PART_SCROLLABLE, LV_STATE_DEFAULT, ext->body_padding_inner);
    lv_page_set_scrollable_fit(page, LV_FIT_TIGHT);

    ancient_page_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrl(page));
    lv_obj_set_signal_cb(lv_page_get_scrl(page), dial_switch_page_scrl_signal);
    ancient_img_signal = NULL;

    lv_page_set_scrl_layout(page, LV_LAYOUT_ROW_MID);
    dial_image_add(page);
    dial_switch_add_element(lv_page_get_scrl(page));

    /*set page to current dial type*/
    dial_conf_t * dial_conf;
    uint8_t cur_type = dial_read_type(ext->psm);
    _LV_LL_READ(diallist.dials, dial_conf) {
        if(dial_conf->dial_type == cur_type) {
            lv_coord_t new_x = lv_obj_get_x(lv_page_get_scrl(page));
            if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL)
                new_x = new_x + ext->move_width * dial_conf->dial_type;
            else
                new_x = new_x - ext->move_width * dial_conf->dial_type;
            lv_obj_set_x(lv_page_get_scrl(page), new_x);
            ext->cur_img_id = dial_conf->dial_type;
            if(ext->imgs[ext->cur_img_id]) lv_obj_add_style(ext->imgs[ext->cur_img_id], LV_IMG_PART_MAIN, &lv_watch_image);
            break;
        }
    }

    if(dial_conf) ext->dail_cur_type = dial_conf->dial_type;
    return obj;
}

void dial_switch_create_btn_action(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_watch_png_cache_all_free();
    uint8_t psm;
    lv_obj_t * label = lv_obj_get_child(btn, NULL);
    if(WATCH_TEXT_ID_PSM_DIAL_REPLACE == lv_obj_get_user_data(label).user_num)
        psm = 1;
    else psm = 0;
    lv_obj_t * obj = dial_switch_create(NULL, psm);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) return;
}

void dial_switch_destroy(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_DIAL_SWITCH);
    dial_switch_prepare_destory(activity_obj);
    lv_obj_del(activity_obj);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void dial_switch_prepare_destory(lv_obj_t * activity_obj)
{
    lv_obj_t * watch_obj;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    if(watch_obj == NULL) return;

    lv_dail_switch_obj_ext_t * ext = lv_obj_get_ext_attr(watch_obj);
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return;
    printf("%s: write psm: %d, cur dial type: %d to system\n", __FUNCTION__, ext->psm, ext->dail_cur_type);
    dial_write_type(ext->dail_cur_type, ext->psm);
    dial_list_destory(&diallist);
    lv_img_cache_invalidate_src(NULL);
}

static void dial_switch_add_element(lv_obj_t * element)
{
    lv_watch_obj_add_element(element);
    return;
}

static lv_obj_t * append_obj(lv_obj_t * page)
{
    lv_dail_switch_obj_ext_t * ext = dial_switch_get_ext(page);
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    lv_obj_t * append_obj = lv_obj_create(page, NULL);
    lv_obj_set_size(append_obj, ext->append_width, lv_obj_get_height(page));
    lv_obj_add_style(append_obj, LV_OBJ_PART_MAIN, &lv_style_transp_tight);
    dial_switch_add_element(append_obj);
    return append_obj;
}

static void dial_switch_img_anim_end(lv_anim_t * a)
{
    lv_obj_t * obj = NULL;
    uint8_t psm = lv_obj_get_user_data(a->var).user_num;
    lv_watch_get_parent_obj(a->var, lv_watch_obj_signal, &obj);
    if(psm) {
        lv_obj_t * mbox = lv_msgbox_create(obj, NULL);
        lv_obj_set_top(mbox, true);
        lv_msgbox_set_text(mbox, (char *)lv_lang_get_text(WATCH_TEXT_ID_PSM_DIAL_SET));
        lv_msgbox_set_anim_time(mbox, 0);
        lv_msgbox_start_auto_close(mbox, DIAL_PSM_SET_TIP_TIME);
        lv_anim_t * anim = lv_anim_get(mbox, NULL);
        lv_anim_set_ready_cb(anim, dial_switch_psm_destroy);
    } else {
        lv_watch_go_home();
        launcher_recreate();
    }
}

static lv_res_t dial_switch_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
{
    lv_res_t res = LV_RES_OK;

    //printf("dial_switch_img_signal, sign=%d\n", sign);
    lv_dail_switch_obj_ext_t * ext = dial_switch_get_ext(img);
    if(ext == NULL) return LV_RES_INV;

    /* Include the ancient signal function */
    if(ancient_img_signal) {
        res = ancient_img_signal(img, sign, param);
        if(res != LV_RES_OK) return res;
    }

    /*when clean up , not to read lv_indev_get_act*/
    if(sign == LV_SIGNAL_CLEANUP) {
        if(ext->imgs) {
            lv_mem_free(ext->imgs);
            ext->imgs = NULL;
        }
        return LV_RES_OK;
    }

    lv_indev_t * indev = lv_indev_get_act();
    lv_point_t point_act;
    lv_indev_get_point(indev, &point_act);
    lv_coord_t x_diff = point_act.x - ext->lv_watch_obj.point_last.x;

    if(sign == LV_SIGNAL_PRESSED) {
        ext->del_activity_en = true;
    } else if(sign == LV_SIGNAL_PRESS_LOST) {
        if(x_diff != 0 && ext->lv_watch_obj.point_last.x != 0) {
            ext->del_activity_en = false;
        }
    } else if(sign == LV_SIGNAL_RELEASED) {
        if(ext->del_activity_en && !lv_indev_is_dragging(lv_indev_get_act())) {
            int8_t latest_cur_img_id = ext->cur_img_id;
            lv_coord_t delta = (LV_HOR_RES - ext->move_width) / 2;
            if(lv_obj_get_base_dir(img) == LV_BIDI_DIR_RTL) {
                if(point_act.x < delta) {
                     if(ext->cur_img_id < ext->img_cnt - 1) ext->cur_img_id ++;
                } else if(point_act.x > LV_HOR_RES - delta) {
                     if(ext->cur_img_id != 0) ext->cur_img_id --;
                }
            } else {
                if(point_act.x < delta) {
                    if(ext->cur_img_id != 0) ext->cur_img_id --;
                } else if(point_act.x > LV_HOR_RES - delta) {
                    if(ext->cur_img_id < ext->img_cnt - 1)  ext->cur_img_id ++;
                }
            }

            if(latest_cur_img_id != ext->cur_img_id) {
                lv_obj_add_style(ext->imgs[latest_cur_img_id], LV_IMG_PART_MAIN, &lv_watch_image_opa1);
                if(ext->imgs[ext->cur_img_id]) lv_obj_add_style(ext->imgs[ext->cur_img_id], LV_IMG_PART_MAIN, &lv_watch_image);

                lv_obj_t * page_scrl = dial_switch_get_page_scrl(img);
                if(page_scrl) {
                    lv_coord_t new_x;
                    lv_coord_t x = lv_obj_get_x(page_scrl);
                    if(lv_obj_get_base_dir(img) == LV_BIDI_DIR_RTL)
                        new_x = (latest_cur_img_id < ext->cur_img_id) ? (x + ext->move_width) : (x - ext->move_width);
                    else
                        new_x = (latest_cur_img_id < ext->cur_img_id) ? (x - ext->move_width) : (x + ext->move_width);
                    lv_watch_set_free_num(page_scrl, ext->psm);
                    lv_obj_set_x_animation(page_scrl, new_x, true, 200, dial_switch_img_anim_end);
                }
                ext->dail_cur_type = ext->cur_img_id;
            } else {
                if(ext->psm) {
                    lv_obj_t * mbox = lv_msgbox_create(img, NULL);
                    lv_msgbox_set_text(mbox, (char *)lv_lang_get_text(WATCH_TEXT_ID_PSM_DIAL_SET));
                    lv_msgbox_set_anim_time(mbox, 0);
                    lv_msgbox_start_auto_close(mbox, DIAL_PSM_SET_TIP_TIME);
                    lv_anim_t * anim = lv_anim_get(mbox, NULL);
                    lv_anim_set_ready_cb(anim, dial_switch_psm_destroy);
                } else {
                    lv_watch_go_home();
                    launcher_recreate();
                }
            }
        } else {
            //printf("recover ext->del_activity_en = true\n");
            //ext->del_activity_en = true;
        }
    }

    return res;
}

static void dial_switch_psm_destroy(lv_anim_t * a)
{
    printf("%s\n", __FUNCTION__);
    dial_switch_destroy();
}

static lv_obj_t * dial_image_add(lv_obj_t * page)
{
    dial_conf_t * dial_conf = _lv_ll_get_head(&diallist.dials);
    const char * img_src;
    img_src = dial_conf->preview_path;
    lv_img_header_t img_header;
    lv_dail_switch_obj_ext_t * ext = dial_switch_get_ext(page);
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    lv_img_decoder_get_info(img_src, &img_header);
    ext->append_width = (lv_obj_get_width(page) - img_header.w - 2 * ext->body_padding_inner) / 2;
    ext->move_width = ext->body_padding_inner + img_header.w;
    append_obj(page);

    ext->img_cnt = diallist.dial_cnt;
    ext->imgs = lv_mem_alloc(sizeof(lv_obj_t *) * (ext->img_cnt));
    LV_ASSERT_MEM(ext->imgs);
    if(ext->imgs == NULL) return NULL;

    for(int8_t i = 0; i < ext->img_cnt; i++) {
        lv_obj_t * content = lv_cont_create(page, NULL);
        lv_obj_add_style(content, LV_CONT_PART_MAIN, &lv_watch_style_transp);
        lv_obj_set_size(content,  img_header.w, lv_obj_get_height(page));
        lv_cont_set_layout(content, LV_LAYOUT_OFF);
        LV_ASSERT_MEM(content);
        if(content == NULL) return NULL;
        /*must set click enable for these content, and lv_watch_obj_add_element(), If not,  no pressed/pressing signals out*/
        lv_obj_set_click(content, true);
        dial_switch_add_element(content);

        /*hor drag in page, must set glue*/
        lv_page_glue_obj(content, true);

        lv_obj_t * img = lv_img_create(content, NULL);
        lv_obj_t * label = lv_label_create(content, NULL);
        lv_img_set_src(img, dial_conf->preview_path);
        lv_label_set_text(label, dial_conf->name);
#if LV_WATCH_SIMULATOR_360 != 0
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
#else
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
#endif
        lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 10);
        if(ext->psm == 0) {
            if(dial_conf->configurable == 1) {
                lv_obj_t * setting = lv_img_create(content, NULL);
                lv_img_set_src(setting, ICON_DIAL_SETTING);
                lv_obj_set_click(setting, true);
                lv_obj_align(setting, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -10);
                lv_watch_set_free_num(setting, dial_conf->dial_type);
                lv_obj_set_event_cb(setting, dial_element_setting);
            }
        }
        dial_conf = _lv_ll_get_next(&diallist.dials, dial_conf);
        lv_obj_add_style(img, LV_IMG_PART_MAIN, &lv_watch_image_opa1);
        lv_obj_align(img, content, LV_ALIGN_CENTER, 0, 0);
#if 1
        /*support img to be clicked*/
        if(ancient_img_signal == NULL) ancient_img_signal = lv_obj_get_signal_cb(img);
        lv_obj_set_signal_cb(img, dial_switch_img_signal);
        lv_obj_set_click(img, true);
        lv_page_glue_obj(img, true);
        dial_switch_add_element(img);
#endif
        ext->imgs[i] = img;
    }

    append_obj(page);

    return page;
}

static void dial_element_setting(lv_obj_t * obj, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;
    lv_obj_t * cont = dial_get_clock_cont();
    lv_clock_ext_t * clock_ext = lv_obj_get_ext_attr(cont);
    clock_ext->configuring = 1;
#if DIAL_USE_CANVAS
    lv_obj_t * bg_img = dial_add_bg_img(cont, ((lv_clock_ext_t *)lv_obj_get_ext_attr(cont))->watch_dial);
#else
    lv_obj_t * bg_img = lv_obj_get_child(cont, NULL);
#endif
    uint8_t dial_type = lv_obj_get_user_data(obj).user_num;
    if(dial_read_type(0) != dial_type) {
        char dsc_file[WATCH_MAX_PATH_LEN] = {0};
        printf("%s: set type %d as cur type\n", __FUNCTION__, dial_type);
        dial_get_dsc_file(dial_type, 0, dsc_file);
        dial_free_element(clock_ext->watch_dial);
        memset(clock_ext->watch_dial, 0, sizeof(watch_dial_t));
        dial_parse(dsc_file, clock_ext->watch_dial);
        dial_init_act_element(clock_ext->watch_dial);
        lv_img_set_src(bg_img, clock_ext->watch_dial->bg_img);
        lv_dail_switch_obj_ext_t * switch_ext = dial_switch_get_ext(obj);
        switch_ext->dail_cur_type = dial_type;
    }
    dial_switch_destroy();
    lv_anim_del(cont, NULL);
    lv_obj_clean(bg_img);
    dial_add_configurable_element(bg_img);
}

static lv_res_t dial_switch_page_scrl_signal(lv_obj_t * page_scrl, lv_signal_t sign, void * param)
{
    lv_res_t res;

    /* Include the ancient signal function */
    res = ancient_page_scrl_signal(page_scrl, sign, param);
    if(res != LV_RES_OK) return res;

    if(sign == LV_SIGNAL_CLEANUP) {
        /*when cleanup, can not invoke lv_indev_get_act */
        return LV_RES_OK;
    }

    res = page_scrl_signal_handler(page_scrl, sign, param);
    if(res != LV_RES_OK) return res;

    return LV_RES_OK;
}

static int aligned_width(int val, lv_coord_t move_width)
{
    bool negative = (val < 0) ? true : false;
    if(val < 0)  val = -val;
    int i = (val + move_width - 1) / move_width - 1;
    int new_val = i * move_width;

    new_val = (val - new_val > move_width / 2) ? (new_val + move_width) : new_val;
    new_val = negative ? -new_val : new_val;
    return new_val;
}

static lv_dail_switch_obj_ext_t * dial_switch_get_ext(lv_obj_t * element)
{
    lv_obj_t * obj = NULL;
    lv_watch_get_parent_obj(element, lv_watch_obj_signal, &obj);
    if(obj == NULL) return NULL;

    lv_dail_switch_obj_ext_t * ext = lv_obj_get_ext_attr(obj);
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    return ext;
}

static lv_obj_t * dial_switch_get_page_scrl(lv_obj_t * element)
{
    lv_obj_t * obj = NULL;
    lv_watch_get_parent_obj(element, lv_watch_obj_signal, &obj);
    if(obj == NULL) return NULL;
    lv_obj_t * page = lv_obj_get_child(obj, NULL);
    if(page == NULL) return NULL;
    lv_obj_t * page_scrl = lv_page_get_scrl(page);
    if(page_scrl == NULL) return NULL;
    return page_scrl;
}

static lv_res_t page_scrl_signal_handler(lv_obj_t * page_scrl, lv_signal_t sign, void * param)
{
    lv_dail_switch_obj_ext_t * ext = dial_switch_get_ext(page_scrl);
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return LV_RES_INV;

    if(sign == LV_SIGNAL_DRAG_END) {
        lv_coord_t new_x = lv_obj_get_x(page_scrl);
        lv_coord_t aligned_new_x = aligned_width(new_x, ext->move_width);
        lv_obj_set_x(page_scrl, aligned_new_x);

        /* update image id */
        ext->cur_img_id = (aligned_new_x < 0) ? -aligned_new_x / ext->move_width : aligned_new_x / ext->move_width;
        if(lv_obj_get_base_dir(page_scrl) == LV_BIDI_DIR_RTL)
            ext->cur_img_id =  diallist.dial_cnt - ext->cur_img_id - 1;
        ext->dail_cur_type = ext->cur_img_id;
    }

    return LV_RES_OK;
}

static void dial_switch_get_dial_list(char * list_path, dial_list_t * dial_list)
{
    lv_fs_file_t list_file;
    dial_conf_t * dial_conf;

    uint8_t res = lv_fs_open(&list_file, list_path, LV_FS_MODE_RD);

    if(LV_FS_RES_OK != res) {
        printf("%s dail list file open fail: %s\n", __FUNCTION__, list_path);
        return;
    }

    uint32_t rn, size, i, j = 0;
    uint8_t line = 0;
    char * temp_buf = NULL;
    lv_fs_size(&list_file, &size);
    temp_buf = lv_mem_alloc(size + 1);
    memset(temp_buf, 0, size + 1);
    lv_fs_read(&list_file, temp_buf, size, &rn);
    if(rn == 0) {
        printf("%s read dial dsc file fail list_path = %s\n", __FUNCTION__, list_path);
        lv_mem_free(temp_buf);
        lv_fs_close(&list_file);
        return;
    }

    for(i = 0; i < rn; i++) {
        if(temp_buf[i] == '\n' || i == rn - 1) {
            if(line % 2 != 0) {
                dial_conf = _lv_ll_ins_tail(&dial_list->dials);
                memset(dial_conf, 0, sizeof(dial_conf_t));
                if(temp_buf[i] != '\n' && i == rn - 1) {
                    i++;
                    j++;
                }
                memcpy(dial_conf->conf_file_path, &temp_buf[i - j], j);
                if(dial_conf->conf_file_path[j - 1] == '\r')
                    dial_conf->conf_file_path[j - 1] = 0;
                if(0 == dial_switch_get_config(dial_conf->conf_file_path, dial_conf))
                    printf("%s %s: conf file wrong\n", __FUNCTION__, dial_conf->conf_file_path);
                else
                    dial_conf->dial_type = dial_list->dial_cnt++;
            }
            line++;
            j = 0;
        } else {
            j++;
        }
    }

    lv_mem_free(temp_buf);
    lv_fs_close(&list_file);
}

static void dial_list_destory(dial_list_t * dial_list)
{
    if(diallist.dial_cnt != 0)
        _lv_ll_clear(&dial_list->dials);

    memset(dial_list, 0, sizeof(dial_list_t));
}

static void dial_list_init(dial_list_t * dial_list, uint8_t psm)
{
    dial_list_destory(&diallist);
    _lv_ll_init(&dial_list->dials, sizeof(dial_conf_t));
    if(psm) {
        dial_switch_get_dial_list(WATCH_DIAL_BUILDIN_AM_LIST_FILE, dial_list);
        dial_switch_get_dial_list(WATCH_DIAL_EXT_AM_LIST_FILE, dial_list);
    } else {
        dial_switch_get_dial_list(WATCH_DIAL_BUILDIN_LIST_FILE, dial_list);
        dial_switch_get_dial_list(WATCH_DIAL_EXT_LIST_FILE, dial_list);
    }

}

static uint8_t dial_switch_get_config(char * conf_path, dial_conf_t * dial_conf)
{
    cJSON * json_root = NULL;
    char * valuestring = NULL;
    lv_fs_file_t file;
    uint8_t res;
    uint32_t size = 0;
    uint32_t br = 0;
    char * content = NULL;

    if(NULL == dial_conf || NULL == conf_path) {
        return 0;
    }

    res = lv_fs_open(&file, conf_path, LV_FS_MODE_RD);
    if(LV_FS_RES_OK != res) {
        printf("%s: %s does not exist\n", conf_path, __FUNCTION__);
        return 0;
    }
    lv_fs_size(&file, &size);
    content = lv_mem_alloc(size + 1);
    memset(content, 0, size + 1);
    lv_fs_read(&file, content, size, &br);
    lv_fs_close(&file);

    if(content) {
        json_root = cJSON_Parse(content);
        lv_mem_free(content);
    }

    if(NULL == json_root) {
        printf("%s: json parse error\n", __FUNCTION__);
        return 0;
    }

    valuestring = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "name"));
    if(valuestring) strncpy(dial_conf->name, valuestring, WATCH_MAX_DIAL_NAME_LEN);

    valuestring = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "preview_img"));
    if(valuestring) strncpy(dial_conf->preview_path, valuestring, WATCH_MAX_PATH_LEN);

    dial_conf->configurable = cJSON_GetIntValue(cJSON_GetObjectItem(json_root, "configurable"));
    printf("%s: name %s, preview %s config %d\n", __FUNCTION__, dial_conf->name, dial_conf->preview_path, dial_conf->configurable);
    cJSON_Delete(json_root);

    return 1;
}
#endif /*USE_LV_WATCH_DIAL_SWITCH*/
